﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core.Lister;
using System.Threading;
using COFE.Core;
using COFE.Core.Utils;
using NUnit.Framework;
using COFE.Core.Entry;

namespace COFE.Core.Actions
{
    public class EntryListActionProvider : ISecondaryPropertyProvider<IEntryList>
    {
        #region Constructor

        #endregion

        #region Methods

        public object[] GetSupportedProperty(IEntryList sourceObj)
        {
            return new object[] {              
                    EntryListActions.Save,
                    EntryListActions.Load,
                    EntryListActions.Remove,
                    EntryListActions.Combine,
                    EntryListActions.Select,
                };
        }

        public bool IsPropertyReadOnly(IEntryList sourceObj, object property)
        {
            return true;
        }


        public PropertyPair GetProperty(IEntryList sourceObj, object property)
        {
            switch ((int)property)
            {
                case (int)EntryListActions.Save:
                    return new PropertyPair(property, (Func<IEntryList, string, IWorkProgress, IEntryList>)Save);
                case (int)EntryListActions.Load:
                    return new PropertyPair(property, (Func<IEntryList, string, IWorkProgress, IEntryList>)Load);
                case (int)EntryListActions.Remove:
                    return new PropertyPair(property, (Func<IEntryList, string, IWorkProgress, IEntryList>)Remove);
                case (int)EntryListActions.Combine:
                    return new PropertyPair(property, (Func<IEntryList, string, IWorkProgress, IEntryList>)Combine);
                case (int)EntryListActions.Select:
                    return new PropertyPair(property, (Func<IEntryList, string, IWorkProgress, IEntryList>)Select);
            }

            throw new NotSupportedException(property.ToString());
        }

        public void SetProperty(IEntryList sourceObj, object property, object value)
        {
            throw new NotSupportedException(property.ToString());
        }



        IEntryList Save(IEntryList input, string param, IWorkProgress progress)
        {
            if (input == null)
                throw new ArgumentException("Input cannot be null.");

            var stringDic = StringUtils.ParamStringToDic(param);

            if (!stringDic.ContainsKey("name"))
                throw new ArgumentException("name not specified.");

            Action<IAutoEntryList, string> registerAuto = (inp, nam) =>
            {
                var autoList = new AutoEntryList(inp.Id, nam, inp.GetFilterString());
                COFEShared.EntryListRegistrar.RegisterEntryList(autoList);
            };

            Action<IEntryList, string> registerCustom = (inp, nam) =>
                {
                    var customList = new CustomEntryList(nam);
                    customList.AddRange(inp.Entries);
                    COFEShared.EntryListRegistrar.RegisterEntryList(customList);
                };

            string name = stringDic["name"];
            if (stringDic.ContainsKey("type"))
            {
                string type = stringDic["type"];
                switch (type)
                {
                    case "auto":
                        if (!(input is IAutoEntryList))
                            throw new ArgumentException("Input entrylist is not an AutoEntryList");
                        registerAuto(input as IAutoEntryList, name);
                        break;
                    case "custom":
                        registerCustom(input, name);
                        break;
                    default:
                        throw new NotSupportedException(type);
                }
            }
            else
                if (input is IAutoEntryList)
                    registerAuto(input as IAutoEntryList, name);
                else registerCustom(input, name);

            return NullEntryList.Create();
        }

        IEntryList Load(IEntryList input, string param, IWorkProgress progress)
        {
            var stringDic = StringUtils.ParamStringToDic(param);

            if (!stringDic.ContainsKey("name"))
                throw new ArgumentException("name not specified.");
            string name = stringDic["name"];

            var retVal = COFEShared.EntryListRegistrar[name];
            if (retVal == null)
                throw new ArgumentException(String.Format("Entrylist {0} not found.", name));

            return retVal;
        }

        IEntryList Remove(IEntryList input, string param, IWorkProgress progress)
        {
            var retVal = Load(input, param, progress);
            var stringDic = StringUtils.ParamStringToDic(param);
            COFEShared.EntryListRegistrar.RemoveEntryList(stringDic["name"]);
            return retVal;
        }

        IEntryList Combine(IEntryList input, string param, IWorkProgress progress)
        {
            var loadedList = Load(input, param, progress);
            var retVal = new CustomEntryList("");

            retVal.AddRange(loadedList.Entries.Union(input.Entries));

            return retVal;
        }


        IEntryList Select(IEntryList input, string param, IWorkProgress progress)
        {
            var stringDic = StringUtils.ParamStringToDic(param);

            int position = 0;
            if (stringDic.ContainsKey("position"))
            {
                int pos;
                if (Int32.TryParse(stringDic["position"], out pos))
                {
                    if (pos < 0)
                        position = Math.Max(0, input.Entries.Count() + pos);
                    else
                        position = pos >= input.Entries.Count() ? input.Entries.Count() - 1 : pos;
                }
            }

            int count = 0;

            if (stringDic.ContainsKey("count"))
            {
                int cnt;
                if (Int32.TryParse(stringDic["count"], out cnt))
                    count = Math.Max(1, cnt);
            }
            List<IFileSystemInfo> entries = input.Entries.ToList();

            var retVal = new CustomEntryList("");

            for (int i = position; i < position + count; i++)
                if (i < entries.Count)
                    retVal.Add(entries[i]);

            return retVal;
        }

        #endregion

        #region Data

        #endregion

        #region Public Properties

        #endregion



    }
}
